<!-- 角色管理 - 弹框 -->
<template>
    <el-dialog
        :title="typeTitle + '角色'"
        v-model="dialogVisible"
        width="45%"
        :close-on-click-modal="false" 
        :close-on-press-escape="true"
        @closed="resetForm(formRef)">
        <el-form :model="form" ref="formRef" :rules="rules" label-width="100px">
            <el-form-item label="角色名称" prop="roleName">
                <el-input v-model="form.roleName" :readonly="billState" placeholder="请输入角色名称"></el-input>
            </el-form-item>
            <el-form-item label="角色顺序" prop="sort">
                <el-input v-model.number="form.sort" :readonly="billState" placeholder="请输入角色顺序"></el-input>
            </el-form-item>
            <el-form-item label="状态" prop="">
                <el-radio-group :disabled="billState" v-model.number="form.state">
                    <el-radio :value="true">正常</el-radio>
                    <el-radio :value="false">停用</el-radio>
                </el-radio-group>
            </el-form-item>
            <el-form-item label="菜单权限" prop="">
                <el-row>
                    <el-col :span="24">
                        <el-checkbox-group :disabled="billState" v-model="checkList" @change='checkboxChange'>
                            <el-checkbox v-for="item in checkboxList" :key="item.value" :value="item.value" :label="item.label" @click="checkboxClick(item.value)">{{ item.label }}</el-checkbox>
                        </el-checkbox-group>
                    </el-col>
                    <el-col :span="24">
                        <MenusTree 
                        ref="MenusTreeRef"
                        :treeData="menuList"
                        :showCheckbox="true"
                        :onClickNode="true"
                        :defaultExpandedKeys="defaultExpandedKeys"
                        :defaultCheckedKeys="defaultCheckedKeys"
                        :checkStrictly="checkStrictly"/>
                    </el-col>
                </el-row>
            </el-form-item>
            <el-form-item label="角色描述" prop="">
                <el-input type="textarea" v-model="form.roleDesc" :readonly="billState" placeholder="角色描述"></el-input>
            </el-form-item>
        </el-form>
        <template #footer>
            <span>
                <el-button type="primary" class="" v-if="dialogState == 'add'" :loading="submitLoading" @click="submitClick">确定</el-button>
                <el-button type="primary" class="" v-if="dialogState == 'update'" :loading="updateLoading" @click="updateClick">确定</el-button>
                <el-button class="" @click="resetForm(formRef)">关闭</el-button>
            </span>
        </template>
    </el-dialog>
</template>

<script setup>
import { nextTick, reactive, ref } from "vue";
import { ElMessage } from 'element-plus';

import { menusApi } from '@/api/system/menus/menus-api';
import { rolesApi } from '@/api/system/roles/roles-api';
import { montageStr, setTreeData, deepClone } from '@/utils/tools-util';

import MenusTree from '@/components/system/menus-tree.vue';
// ========================= 弹框控制 =========================
let dialogVisible = ref(false);
let dialogState = ref('add');
let defaultExpandedKeys = ref([]);
let defaultCheckedKeys = ref([]);
let MenusTreeRef = ref(); // 菜单组件ref
let checkboxList = reactive([
    {label: '展开/折叠', value: 1},
    {label: '全选/全不选', value: 2},
    {label: '父子联动', value: 3},
]);

// 打开弹框
const onShowDialog = (type, row) => {
    getMenusData(data => {
        type === 'view' ? menuList.value = setTreeData(data, 'id', 'parentId', 'children', true, true) : 
        menuList.value = setTreeData(data, 'id', 'parentId', 'children');
        if(type === 'view' || type === 'update') {
            // 禁用
            nextTick(() => {
                for(let key in form) {
                    form[key] = row[key];
                };
                // 默认为展开
                checkList.value = [1];
                MenusTreeRef.value.expandHandle(true);
                // 当前状态为全选
                row.menus.length == data.length && (checkList.value.push(2));
                // 取消父子联动
                checkStrictly.value = true;
                // 默认选中的数据
                defaultCheckedKeys.value = montageStr(row.menus, 'id', false);
            });
        }else {
            checkStrictly.value = false;
        };
    });
    dialogState.value = type;
    dialogVisible.value = true;
};

// 组件向外暴露属性或方法
defineExpose({
    onShowDialog
});

// 计算属性
const typeTitle = computed(() => {
    if(dialogState.value == 'add') return '新增';
    if(dialogState.value == 'update') return '修改';
    if(dialogState.value == 'view') return '查看';
});

const billState = computed(() => {
    if(dialogState.value != 'view') return false;
    return true;
})

// ========================= 菜单数据 =========================
let menuList = ref([]);
let menuAllData = reactive([]);
async function getMenusData(cb) {
    const res = await menusApi.list();
    let data = res.data.data;
    menuAllData = data;
    cb(data);
};

// ========================= 表单 =========================
const form = reactive({
    id:0,               // 主键
    roleName:'',        // 角色名称
    sort:'',            // 显示顺序
    state: true,        // 状态
    menuIds:[],         // 菜单
    roleDesc:'',        // 描述
    createdAt:'',       // 创建时间
    updatedAt:'',       // 更新时间
});
const rules = reactive({
    roleName: [
        { required: true, message: '角色名称不能为空', trigger: 'blur' }
    ],
    sort: [
        { required: true, message: '角色顺序不能为空', trigger: 'blur' }
    ],
})

// 表单操作
const formRef = ref();
let submitLoading = ref(false);
// 提交
function submitClick() {
    formRef.value.validate(async (valid) => {
        try {
            if(valid) {
                submitLoading.value = true;
                let menuIds = MenusTreeRef.value.getCheckedKeys();
                let date = new Date();
                form.createdAt = date;
                form.updatedAt = date;
                form.menuIds = menuIds;
                const res = await rolesApi.create(form);
                if(res.meta.status !== 200) throw new Error(res.meta.msg);
                ElMessage.success('新增成功');
                submitLoading.value = false;
                dialogVisible.value = false;
                emits('updateMenusList');
            };
        } catch (e) {
            console.error(e);
            ElMessage.error(e.message);
        } finally {
            submitLoading.value = false;
        };
    })
};

// 更新
let updateLoading = ref(false);
function updateClick() {
    formRef.value.validate(async (valid) => {
        try {
            if(valid) {
                updateLoading.value = true;
                let menuIds = MenusTreeRef.value.getCheckedKeys();
                let date = new Date();
                form.updatedAt = date;
                form.menuIds = menuIds;
                const res = await rolesApi.update(form);
                if(res.meta.status !== 200) throw new Error(res.meta.msg);
                ElMessage.success('修改成功');
                updateLoading.value = false;
                dialogVisible.value = false;
                emits('updateMenusList');
            };
        } catch (e) {
            console.error(e);
            ElMessage.error(e.message);
        } finally {
            updateLoading.value = false;
        };
    });
};

// ========================= 菜单权限 - 选择 =========================
const checkList = ref([3]);
// 菜单权限 - 快捷操作
let checkStrictly = ref(false);
let activeVal = ref(3);
// 获取当前value
function checkboxClick(value) {
    activeVal.value = value;
};
function checkboxChange(value) {
    if(activeVal.value == 1 && value.indexOf(1) != -1) {
        MenusTreeRef.value.expandHandle(true);
    }else if(activeVal.value == 1) {
        MenusTreeRef.value.expandHandle(false);
    };
    if(activeVal.value == 2 && value.indexOf(2) != -1) {
        checkStrictly.value ? 
        setCheckedId(menuList.value, true, false) : 
        setCheckedId(menuAllData, true, true);
    }else if(activeVal.value == 2) {
        MenusTreeRef.value.resetChecked();
    };
    if(activeVal.value == 3 && value.indexOf(3) != -1) {
        checkStrictly.value = false;
    }else if(activeVal.value == 3) {
        checkStrictly.value = true;
    };
};

// 设置全选反选id
function setCheckedId(data, checked, deepChecked) {
    for(let item of data) {
        MenusTreeRef.value.setChecked(item.id, checked, deepChecked);
    };
};

// ========================= 定义发射给父组件的方法 =========================
const emits = defineEmits(['updateMenusList']);

// ========================= 重置表单 =========================
function resetForm(refFormName) {
    refFormName.resetFields(); // 重置表单
    form.roleDesc = '';
    form.state = true;
    checkList.value = [3];
    defaultCheckedKeys.value = [];
    MenusTreeRef.value.expandHandle(false);
    checkStrictly.value = true;
    dialogVisible.value = false;
};
</script>

<style lang="scss" scoped>

</style>